using System;
using System.Collections.Generic;
using Arcane.Source.Data;
using Godot;

namespace Arcane.Source.Combat.Items
{
    public class RuneController : BaseItem
    {
        public static readonly StringName NAME = "rune_controller";

        public event Action<Element> OnRuneElim;

        private readonly RuneMatch _match;
        public RuneMatch Match => _match;

        private readonly List<StringName> _runeNames = [];
        public IEnumerable<StringName> RuneNames
        {
            get => _runeNames;
            set
            {
                _runeNames.Clear();
                _runeNames.AddRange(value);
            }
        }

        private Entity _host;

        public RuneController(int col, int row, IEnumerable<StringName> runeNames)
        {
            RuneNames = runeNames;
            _match = new RuneMatch(col, row, _runeNames.Count);
        }

        public override void OnReady(Entity host)
        {
            _host = host;

            _match.Setup();
            _match.OnEliminate += OnEliminate;
            _match.OnRuneEliminate += OnRuneEliminate;

            host.OnTimeScaleChange += SetMatchTimeScale;
        }

        public override void OnTick(Entity host)
        {
            _match.Tick();
        }

        public override void OnRemove(Entity host)
        {
            _match.OnEliminate -= OnEliminate;
            _match.OnRuneEliminate -= OnRuneEliminate;

            host.OnTimeScaleChange -= SetMatchTimeScale;

            _host = null;
        }

        private void OnEliminate(int count)
        {
            _host.Attack(_host.GetTarget(1), DamageType.Common, count);
            _host.Charge(count);
        }

        private void OnRuneEliminate(int type, int level, int col, int row)
        {
            var proto = GameDB.Rune.Get(_runeNames[type]);
            OnRuneElim?.Invoke(proto.element);
            if (level > 0)
            {
                proto.Cast(_host, level);

            }
        }

        private void SetMatchTimeScale(float timeScale)
        {
            _match.TimeScale = timeScale;
        }
    }
}